// Copyright (C) 1953-2024 NUDT
// Verilog module name - sync_receiveport_timestamp_record
// Version: V4.3.0.20240120
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         sync_receiveport_timestamp_record
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module sync_receiveport_timestamp_record#(parameter ptp_rx_offset = 16'd192)
(
    i_clk  ,
    i_rst_n,
   
    iv_data  ,
    i_data_wr,
    i_osm_sync_rx_pulse,
	iv_local_counter,
	
    ov_data       ,
    o_data_wr     
);
//I/O

//clk & rst
input                   i_clk  ;
input                   i_rst_n;

//input
input      [8:0]     iv_data  ;
input                i_data_wr;
input                i_osm_sync_rx_pulse       ;
input     [39:0]     iv_local_counter       ;

//output
output  reg [8:0]       ov_data             ;
output  reg             o_data_wr           ;

//internal wire
//reg         [125:0]     rv_data;
reg         [134:0]     rv_data;
reg         [10:0]      rv_byte_cnt; 
reg			[39:0]		rv_sync_rx_pit;
reg 		[15:0]      rv_eth_type         ;
reg 		[7:0]       rv_ptp_messagetype  ;
reg 		[7:0]       rv_ptp_messagesubtype;
//在接收到PRX模块产生的脉冲信号osm_sync_rx_pulse后，记录当前的local_counter值，记为sync_rx_pit
reg   r_osm_sync_rx_pulse;
always @(posedge i_clk or negedge i_rst_n) begin
	if(!i_rst_n) begin
		rv_sync_rx_pit<= 40'b0;
		r_osm_sync_rx_pulse <= 1'b0;
	end
	else begin
	    r_osm_sync_rx_pulse <= i_osm_sync_rx_pulse;
		if((r_osm_sync_rx_pulse==1'b0)&&(i_osm_sync_rx_pulse==1'b1))begin 
			rv_sync_rx_pit<= iv_local_counter - {24'd16,16'b0}- {8'b0,ptp_rx_offset,16'b0};
		end
		else begin
			rv_sync_rx_pit<= rv_sync_rx_pit;
		end
	end
end

//为了根据报文长度/类型、TSMP报文类型和子类型来识别Sync封装报文，设计135bit的寄存器rv_data，采用移位寄存器方式来缓存14拍数据；
//同时维护一个11bit计数器rv_byte_cnt（从11’b0开始计数）来统计当前接收到的数据在报文中的偏移量
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n) begin
        //rv_data  <= 126'b0;
		rv_data  <= 135'b0;
        rv_byte_cnt  <= 11'b0;
    end
    else begin
        if(i_data_wr)begin
            rv_byte_cnt <= rv_byte_cnt +1'b1;
            //rv_data     <= {rv_data[116:0],iv_data};
			rv_data     <= {rv_data[125:0],iv_data};
        end
        else begin
            //rv_data     <= {rv_data[116:0],9'b0}; 
			rv_data     <= {rv_data[125:0],9'b0};
            rv_byte_cnt <= 11'b0;           
        end
    end
end 

//识别sync报文并在opensync头中存放时间戳    
reg         [3:0]       rv_srp_state;
localparam  IDLE_S             			= 4'd0,
            TRAN_PKT_S         			= 4'd1,
            DEPOSIT_TIMESTAMP_S         = 4'd2;    //在opensync头中存放时间戳        
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        ov_data             <= 9'b0;
        o_data_wr           <= 1'b0;        
        rv_srp_state        <= IDLE_S;
    end
    else begin
        case(rv_srp_state)
            IDLE_S:begin
//sync报文在opensync头中存放时间戳
                if(rv_byte_cnt == 11'd15)begin
					rv_eth_type				<={rv_data[25:18],rv_data[16:9]};
					rv_ptp_messagetype		<=rv_data[7:0];
					rv_ptp_messagesubtype	<=iv_data[7:0];				
                    if(({rv_data[25:18],rv_data[16:9]} == 16'hff01)&&(rv_data[7:0]==8'h06)&&(iv_data[7:0]==8'h01))begin//sync					
                        o_data_wr                   <= 1'b1;
                        //ov_data                     <= rv_data[125:117];
						ov_data                     <= rv_data[134:126];
                        rv_srp_state                <= DEPOSIT_TIMESTAMP_S;                         
					end
//非sync报文直接输出
					else begin 
						o_data_wr                   <= 1'b1;
                        //ov_data                     <= rv_data[125:117]; 
						ov_data                     <= rv_data[134:126];
                        rv_srp_state                <= TRAN_PKT_S;
					end
				end
//
				else begin
                    ov_data             <= 9'b0;
                    o_data_wr           <= 1'b0;        
                    rv_srp_state        <= IDLE_S;             
                end
            end
//传输			
            TRAN_PKT_S:begin
                
				if(rv_data[134] == 1'b1)begin  
				//if (iv_data[8]==1)begin
					ov_data    <= rv_data[134:126];
					rv_srp_state    <= IDLE_S;
					//o_data_wr           <= 1'b0;	
                end
                else begin
					o_data_wr           <= 1'b1;
					ov_data            <= rv_data[134:126]; 
                    rv_srp_state    <= TRAN_PKT_S;
                end
            end
//存放时间戳 			
            DEPOSIT_TIMESTAMP_S:begin   
                o_data_wr           <= 1'b1;                
				if(rv_byte_cnt<11'd39)begin
					case(rv_byte_cnt)
						11'd34:		ov_data<= {1'b0,rv_sync_rx_pit[39:32]};
						11'd35:		ov_data<= {1'b0,rv_sync_rx_pit[31:24]};
						11'd36:		ov_data<= {1'b0,rv_sync_rx_pit[23:16]};
						11'd37:     ov_data<= {1'b0,rv_sync_rx_pit[15:8]};
						11'd38:begin
							ov_data<= {1'b0,rv_sync_rx_pit[7:0]};
							rv_srp_state    <= TRAN_PKT_S;
						end
						default:	//ov_data<= rv_data[125:117];
							ov_data <= rv_data[134:126];
					endcase
				end				                
                else begin
					//ov_data<= rv_data[125:117];
					ov_data    <= rv_data[134:126];
                    rv_srp_state    <= TRAN_PKT_S;                    
                end
            end
//            
            default:begin
                ov_data             <= 9'b0;
                o_data_wr           <= 1'b0;              
                rv_srp_state        <= IDLE_S;     
            end
        endcase
    end
end   
endmodule
